#include "qe_log.h"
#include "qe_interrupt.h"
#include "libfdt.h"



QELOG_DOMAIN("qe-interrupt");



#if (CONFIG_PORT_INTERRUPT_MGMT)
qe_ret qe_weak qe_irq_enable(int irq)
{
    (void)irq;
    return qe_ok;
}

void qe_weak qe_irq_disable(int irq)
{
    (void)irq;
}

qe_ret qe_weak qe_irq_register(int irq, qe_irq_handler handler, void *ref)
{
    (void)irq;
    (void)handler;
    (void)ref;
    return qe_ok;
}

void qe_weak qe_irq_unregister(int irq)
{
    (void)irq;
}

void qe_weak qe_irq_set_priority_trigger_type(qe_u32 irq, qe_u8 prior, qe_u8 trigger)
{
    (void)irq;
    (void)prior;
    (void)trigger;
}

qe_bool qe_weak qe_is_interrupt_context()
{
    return qe_false;
}
#endif

void qe_weak qe_intc_mount(qe_irq_handler handler, void *args)
{
}

qe_const_str qe_of_get_interrupt_parent_name(const void *fdt, qe_u32 offset)
{
    int len;
    int parent_offset;
    const qe_u32 *prop_parent;

    prop_parent = fdt_getprop(fdt, offset, "interrupt-parent", &len);
    if (!prop_parent) {
        return QE_NULL;
    }

    parent_offset = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*prop_parent));
    if (parent_offset < 0) {
        return QE_NULL;
    }

    return fdt_get_name(fdt, parent_offset, QE_NULL);
}

qe_ret qe_intc_register(qe_intc_dev *intc, qe_const_str name, qe_intc_ops *ops)
{
    qe_dev *dev;

    dev = &intc->dev;
    
    if (!ops->irq_register ||
        !ops->irq_unregister ||
        !ops->irq_enable ||
        !ops->irq_disable) {
        qe_error("invalid ops");
        return qe_err_param;
    }

    dev->type = QE_DEV_INTC;
    dev->rx_indicate = QE_NULL;
    dev->tx_complete = QE_NULL;

    intc->ops = ops;

    return qe_dev_register(dev, name, 0x0);
}

qe_ret qe_intc_irq_register(qe_intc_dev *dev,
    qe_int irq, qe_irq_handler handler, void *args)
{
    return dev->ops->irq_register(dev, irq, handler, args);
}

void qe_intc_irq_unregister(qe_intc_dev *dev, qe_int irq)
{
    return dev->ops->irq_unregister(dev, irq);
}

qe_ret qe_intc_irq_enable(qe_intc_dev *dev, qe_int irq)
{
    return dev->ops->irq_enable(dev, irq);
}

void qe_intc_irq_disable(qe_intc_dev *dev, qe_int irq)
{
    return dev->ops->irq_disable(dev, irq);
}